package com.med.meddataintegrator.admin.config;



import com.med.meddataintegrator.jwt.config.JwtAuthenticationSecurityConfig;
import com.med.meddataintegrator.jwt.filter.TokenFilter;
import com.med.meddataintegrator.jwt.handle.RestAccessDeniedHandler;
import com.med.meddataintegrator.jwt.handle.RestAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 *
 *  Security总体配置类 进行统筹
 *
 * 在 configure() 方法中
 *  1. 禁用了 CSRF（Cross-Site Request Forgery）攻击防护。
 *  2. 还禁用了表单登录，
 *  3. 并应用了 JWT 相关的配置类 JwtAuthenticationSecurityConfig。该配置类处理 JWT 相关的认证逻辑。
 *  4. 配置会话管理这块，将会话策略设置为无状态（STATELESS），适用于前后端分离的情况，无需创建会话。
 *
 *  prePostEnabled = true 表示启用 @PreAuthorize 和 @PostAuthorize 注解，方法级别
 *  securedEnabled = true 表示启用 @Secured 注解。
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)  // 启动方法级别的安全性设置
public class WebSecurityConfig {

    // 自定义认证逻辑的实现 在其内部设置校验的URl 路径
    @Autowired
    private JwtAuthenticationSecurityConfig jwtAuthenticationSecurityConfig;

    @Autowired
    private RestAccessDeniedHandler deniedHandler;

    @Autowired
    private RestAuthenticationEntryPoint authEntryPoint;

    // 创建一个 TokenFilter 对象，用于处理 JWT 相关的认证逻辑
    @Bean
    public TokenFilter tokenAuthenticationFilter() {
        return new TokenFilter();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable() // 禁用 csrf
                .formLogin().disable() // 禁用表单登录
                .apply(jwtAuthenticationSecurityConfig) // 设置用户登录认证相关配置
                .and()
                .authorizeHttpRequests(authorize -> authorize
                        .mvcMatchers("/mdi/v1/user/**").permitAll() // 对于登录 注册 退出请求需要放行
                        .mvcMatchers("/mdi/v1/admin/**").authenticated() // 认证所有以 /mdi/v1/admin 为前缀的 URL 资源需要身份认证
                        .mvcMatchers("/mdi/v1/patient/**").authenticated() // 认证所有以 /mdi/v1/admin 为前缀的 URL 资源需要身份认证
                        .anyRequest().permitAll() // 其他都需要放行，无需认证
                )
                .httpBasic().authenticationEntryPoint(authEntryPoint) // 处理用户未登录访问受保护的资源的情况
                .and()
                .exceptionHandling(exceptionHandling -> exceptionHandling
                        .accessDeniedHandler(deniedHandler) // 处理登录成功后访问受保护的资源，但是权限不够的情况
                )
                .sessionManagement(sessionManagement -> sessionManagement
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 前后端分离，无需创建会话
                )
                .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) // 将 Token 校验过滤器添加到用户认证过滤器之前
                .cors(); // 启用 CORS 配置
        return http.build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().antMatchers("/ignore/**");
    }
}